//
//  AppDelegate+YZPush.m
//  VET
//
//  Created by lixiaoyi on 2018/7/21.
//  Copyright © 2018年 YZ. All rights reserved.
//

#import "AppDelegate+YZPush.h"
#import "YZChatUtils.h"

#import "YZUser.h"
#import "YZMainTabBarController.h"
#import "YZUser.h"
#import "YZChatUtils.h"
#import "varint.h"
#import "ChatHeader.h"
#import "YZNetworkConfig.h"
#import <objc/runtime.h>

@interface AppDelegate ()

// 待读字节
@property (nonatomic) unsigned long long bufferSize;

// 缓冲区
@property (nonatomic, strong) NSMutableData *buffer;

@end

@implementation AppDelegate (YZPush)

static char *BufferSizeKey = "BufferSizeKey";
static char *BufferKey = "BufferKey";

- (void)push:(UIApplication *)application {
    
    // 注册Push
    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];
    }
    
    
#if TARGET_IPHONE_SIMULATOR
    [YZUser sharedInstance].deviceToken = @"";
#endif
}

#pragma mark - PUSH
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *deviceTokenStr = [YZChatUtils convertDataToHexStr:deviceToken];
    NSLog(@"token_Str------>%@",deviceTokenStr);
    [YZUser sharedInstance].deviceToken = deviceTokenStr ? : @"";
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    
    NSLog(@"userInfo == %@",userInfo);
    NSString *message = [(NSDictionary *)[userInfo objectForKey:@"aps"] objectForKey:@"alert"];

    NSString *uid = [userInfo objectForKey:@"sender"] ? : @"";
    NSLog(@"消息通知的发送uid:%@",uid);
    
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    YZMainTabBarController *tabViewController = (YZMainTabBarController *) appDelegate.window.rootViewController;
    [tabViewController setSelectedIndex:1];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"regist push fail--->%@",[error description]);
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    self.bufferSize = 0;
    self.buffer = [NSMutableData data];
    [ClientSocket shareSocket].socketDelegate = self;
    [self doSendMessage:nil mediaType:@"" messageType:@"close"];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
//    [self openSocket];
}

#pragma mark - 发送断开连接
- (void)doSendMessage:(NSData *)dMessage
            mediaType:(NSString *)mediaType
          messageType:(NSString *)messType{
    
    // 消息
    ImMessage *_mess = [YZChatUtils createMessage:@"YZIMP"
                                          version:@"1.0"
                                           userId:[YZUser sharedInstance].uid
                                        userToken:[YZUser sharedInstance].token
                                        messageId:1
                                      messageType:messType
                                      messageTime:[[YZChatUtils getTimeInterval2] integerValue] termType:@"iOS"
                                         receiver:@""
                                           sender:@""
                                    ctrlMessageId:0
                                        mediaType:mediaType
                                         playload:nil];
    
    // 序列化
    NSData *allData = [_mess data];
    
    // 消息长度
    unsigned long long number = [allData length];
    char* str = calloc(7, sizeof(char));
    unsigned char bts;
    varint_encode(number, str, 7, &bts);
    NSData *headVarint = [NSData dataWithBytes:str length:bts];
    NSLog(@"headVarint>>>%@",headVarint);
    free(str);
    
    // 总个消息
    NSMutableData *totalData = [NSMutableData dataWithData:headVarint];
    [totalData appendData:allData];
    
    
    [[ClientSocket shareSocket].socket writeData:totalData withTimeout:-1 tag:0];
    
}

#pragma mark - ClientSocketDelegate
- (void)clientSocket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"建立连接成功");
    [[ClientSocket shareSocket].socket readDataWithTimeout:-1 tag:101];
    [ClientSocket shareSocket].connectd = YES;
    // 开启定时器
    if ([ClientSocket shareSocket].connectTimer) {
        [[ClientSocket shareSocket].connectTimer invalidate];
        [ClientSocket shareSocket].connectTimer = nil;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [[ClientSocket shareSocket] addTimer];
    });
}

- (void)clientSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    
    if (100 == tag) {
        // 心跳
    }
    else if (101 == tag) {
        // conn
        NSString *text = [YZChatUtils convertDataToHexStr:data];
        NSString *printText = [NSString stringWithFormat:@"服务器返回--->%@",text];
        NSLog(@"%@",printText);
        char *str = (char *)[data bytes];
        unsigned char bts;
        unsigned long long r = varint_decode(str, 7, &bts);
        
        int btsLen = (int)bts;
        // 反序列化
        NSMutableString *realStr = [NSMutableString string];
        if (r * 2 <= text.length - btsLen * 2) {
            NSString *tempStr = [text substringWithRange:NSMakeRange(btsLen * 2, r * 2)];
            realStr = [NSMutableString stringWithString:tempStr];
            
            NSData *realData = [YZChatUtils dataFormHexString:realStr];
            ImMessage *p = [ImMessage parseFromData:realData error:nil];
            //            DLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                
                // 给服务器发送ack,确认收到离线消息
                [[ClientSocket shareSocket] doAck:p.messageId];
            };
        }
    } else {
        [self readBytes:data];
    }

    
    // 继续接收数据
    [[ClientSocket shareSocket].socket readDataWithTimeout:-1 tag:0];
}

- (void)readBytes:(NSData *)data {
    
    // 过滤心跳包
    NSString *text = [YZChatUtils convertDataToHexStr:data];
    if ([self isDelayHeartRecData:text]) {
        NSLog(@"接收心跳OK");
        [ClientSocket shareSocket].receHearDt = [NSDate date];
        NSTimeInterval interlTimer = [[ClientSocket shareSocket].receHearDt timeIntervalSinceDate:[ClientSocket shareSocket].sendHeartDt];
        if (interlTimer < HEART_TIME * 2) {
            interlTimer = 0;
            return;
        } else {
//            // 连接失效，客户端关闭socket并重新建立连接
//            NSLog(@"心跳失效，重新连接");
//
//            // 重新连接
//            dispatch_async(dispatch_get_main_queue(), ^{
//                [[ClientSocket shareSocket] autoConnection];
//            });
        }
    }
    
    // 如果待读字节数大于0
    if (self.bufferSize > 0) {
        if (data.length < self.bufferSize) {
            // 继续读
            self.bufferSize = self.bufferSize - data.length;
            [self.buffer appendData:data];
        } else {
            NSData *temp = [data subdataWithRange:NSMakeRange(0, self.bufferSize)];
            [self.buffer appendData:temp];
            // 解析数据
            ImMessage *p = [ImMessage parseFromData:self.buffer error:nil];
            NSLog(@"p>>>%@",p);
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
                [self clearSocket];
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
            };
            
            // 剩余的再处理一次
            NSUInteger leftInt = data.length - self.bufferSize;
            if (leftInt > 0) {
                NSData *leftData = [data subdataWithRange:NSMakeRange(self.bufferSize, data.length - self.bufferSize)];
                
                // 重置buffer
                self.bufferSize = 0;
                self.buffer = [NSMutableData data];
                
                [self readBytes:leftData];
            } else {
                // 重置buffer
                self.bufferSize = 0;
                self.buffer = [NSMutableData data];
            }
        }
    } else {
        char *str = (char *)[data bytes];
        unsigned char bts;
        unsigned long long r = varint_decode(str, 7, &bts);
        int btsLen = (int)bts;
        if (data.length < r + btsLen) {
            self.bufferSize = r - data.length + btsLen;
            NSData *appData = [data subdataWithRange:NSMakeRange(btsLen, data.length - btsLen)];
            [self.buffer appendData:appData];
        } else if (data.length == r + btsLen) {
            // 解析数据
            NSData *tempData = [data subdataWithRange:NSMakeRange(btsLen, r)];
            ImMessage *p = [ImMessage parseFromData:tempData error:nil];
            NSLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
                [self clearSocket];
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
            };
        } else if (data.length > r + btsLen) {
            // 粘包
            NSData *appData = [data subdataWithRange:NSMakeRange(r + btsLen + btsLen, data.length - r - btsLen - btsLen)];
            [self.buffer appendData:appData];
            NSData *dealData = [data subdataWithRange:NSMakeRange(btsLen, r)];
            
            // 解析数据
            ImMessage *p = [ImMessage parseFromData:dealData error:nil];
            NSLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
                [self clearSocket];
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
            };
            
            // 剩余的再处理一次
            NSUInteger leftInt = data.length - btsLen - r;
            if (leftInt > 0) {
                NSData *leftData = [data subdataWithRange:NSMakeRange(btsLen + r, data.length - btsLen - r)];
                
                // 重置buffer
                self.bufferSize = 0;
                self.buffer = [NSMutableData data];
                
                [self readBytes:leftData];
            } else {
                // 重置buffer
                self.bufferSize = 0;
                self.buffer = [NSMutableData data];
            }
        }
    }
}

#pragma mark - setter && getter

- (void)setBuffer:(NSMutableData *)buffer {
    objc_setAssociatedObject(self, BufferKey, buffer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSMutableData *)buffer {
    return objc_getAssociatedObject(self, BufferKey);
}

- (void)setBufferSize:(unsigned long long)bufferSize {
    objc_setAssociatedObject(self, BufferSizeKey, @(bufferSize), OBJC_ASSOCIATION_ASSIGN);
}

- (long long)bufferSize {
    return [objc_getAssociatedObject(self, BufferSizeKey) intValue];
}

#pragma mark - clear
- (void)clearSocket {
    [ClientSocket shareSocket].socketDelegate = nil;
    [[ClientSocket shareSocket] disConn];
    [ClientSocket attempDealloc];
}

- (void)openSocket {
    [ClientSocket shareSocket].socketHost = [YZNetworkConfig getImDomain][@"ip"];
    [ClientSocket shareSocket].socketPort = [[YZNetworkConfig getImDomain][@"port"] integerValue];
    [[ClientSocket shareSocket] autoConnection];
    [ClientSocket shareSocket].socketDelegate = self;
}

// 处理接收服务端返回心跳延迟的情况，心跳返回：100000
- (BOOL)isDelayHeartRecData:(NSString *)recStr{
    BOOL isDelay = NO;
    NSUInteger num = 0;
    NSUInteger len = recStr.length;
    num = [YZChatUtils cauculateTimer:recStr subStr:@"100000"];
    if (num > 0) {
        if (num * 6 == len) {
            isDelay = YES;
        }
    }
    
    return isDelay;
}

@end
